/*
 * @Author: 13177709051 3506463075@qq.com
 * @Date: 2024-12-03 15:56:48
 * @LastEditors: 13177709051 3506463075@qq.com
 * @LastEditTime: 2024-12-03 16:15:30
 * @FilePath: /highly-concurrent-server/example/request.cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */

// 正则表达式(regular expression)描述了⼀种字符串匹配的模式（pattern），可以⽤来检查⼀个串是否
// 含有某种⼦串、将匹配的⼦串替换或者从某个串中取出符合某个条件的⼦串等。
// 正则表达式的使⽤，可以使得HTTP请求的解析更加简单（这⾥指的时程序员的⼯作变得的简单，这并
// 不代表处理效率会变⾼，实际上效率上是低于直接的字符串处理的），使我们实现的HTTP组件库使⽤
// 起来更加灵活。

#include <iostream>
#include <string>
#include <regex>

int main()
{
    // HTTP请求行格式 : GET /bitejiuyeke/login?user=xiaoming&pass=123123 HTTP/1.1\r\n
    std::string str = "GET /bitejiuyeke/login?user=xiaoming&pass=123123 HTTP/1.1\r\n";
    std::smatch matches;
    // 请求方法的匹配 GET HEAD POST PUT DELETE ....
    std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?", std::regex::icase);
    // GET|HEAD|POST|PUT|DELETE 表示匹配并提取其中任意一个字符串
    // [^?]* [^?] : 匹配非问号字符, 后面的 * 表示 0 次或者多次
    //  \\?(.*) \\? 表示原始的 ? 字符 (.*) 表示提取 ? 之后的任意字符 0 次或者多次, 直到遇到空格
    // HTTP/1\\.[01] 表示匹配以 HTTP/1. 开始, 后边有个0或1的字符串
    // (?:\n|\r\n)? (? ....) 表示匹配某个格式字符串, 但是不提取, 最后的 ? 表示的是匹配前边的表达式0次或者1次

    bool ret = std::regex_match(str, matches, e);
    if(ret == false)
    {
        return -1;
    }
    std::string method = matches[1];
    std::transform(method.begin(), method.end(), method.begin(), ::toupper);
    // std::transform 将 method 转换为大写，确保输出始终是大写形式。
    // std::transform 会逐个字符地处理 method 字符串，从 method.begin() 到 method.end() 之间的字符。
    // 对于每个字符，::toupper 会将其转换为大写（如果该字符是小写字母的话）。
    // 结果被直接存回原字符串 method 中，因此原字符串会被修改为全大写形式。
    std::cout << method << std::endl;
    for(int i = 0; i < matches.size(); i++)
    {
        std::cout << i << " : ";
        std::cout << matches[i] << std::endl; 
    }
    return 0;
}

// (GET|HEAD|POST|PUT|DELETE):
// GET|HEAD|POST|PUT|DELETE 匹配请求方法，常见的 HTTP 请求方法如 GET、HEAD、POST、PUT、DELETE 等。
// 使用 () 进行捕获，表示提取匹配到的请求方法。
// ([^?]*):
// [^?]* 匹配请求路径部分（即不包含 ? 的字符），[^?] 表示匹配任何不含问号 ? 的字符，* 表示匹配 0 次或多次。
// 这一部分会捕获请求的路径，如 /bitejiuyeke/login。
// (?:\\?(.*))?:
// (?:...) 是一个非捕获组，表示这个部分是用来匹配，但是不需要提取它的内容。
// \\? 匹配字面意义上的问号字符 ?。
// (.*) 匹配并捕获 ? 后面的查询字符串，.* 表示任意字符（包括 ? 后面的所有字符）。
// ? 表示这一部分（查询字符串）是可选的，如果 URL 中没有查询参数，该部分将不匹配。
// (HTTP/1\\.[01]):
// 匹配 HTTP 版本，要求以 HTTP/1. 开头，后跟 0 或 1，表示版本 HTTP/1.0 或 HTTP/1.1。
// (?:\n|\r\n)?:
// 非捕获组，用来匹配请求行的结束符，可以是 \n（Unix 风格换行）或 \r\n（Windows 风格换行）。? 表示这一部分是可选的。
// 标志：
// std::regex::icase: 表示正则表达式匹配时忽略大小写。